package cn.fintecher.gis.service;

import cn.fintecher.gis.entity.*;
import cn.fintecher.gis.enums.*;
import cn.fintecher.gis.model.MapSpotData;
import cn.fintecher.gis.model.StatisticsModel;
import cn.fintecher.gis.model.request.StatisticalRequest;
import cn.fintecher.gis.model.response.LandStatisticalResponse;
import cn.fintecher.gis.model.response.PatrolStatisticalResponse;
import cn.fintecher.gis.model.response.ProjectResponse;
import cn.fintecher.gis.postgis.PostGISService;
import cn.fintecher.gis.respository.*;
import cn.fintecher.gis.utils.DateUtil;
import com.querydsl.core.BooleanBuilder;
import org.apache.commons.lang3.StringUtils;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Service("statisticalItemService")
public class StatisticalItemService extends BaseService {

    private final Logger log = LoggerFactory.getLogger(StatisticalItemService.class);

    @Autowired
    private PatrolInfoRepository patrolInfoRepository;

    @Autowired
    private LandDisasterRepository landDisasterRepository;

    @Autowired
    protected FlowService flowService;

    @Autowired
    private FlowInfoRepository flowInfoRepository;

    @Autowired
    private FlowHistoryRepository flowHistoryRepository;

    @Autowired
    private LayerRelationRepository layerRelationRepository;

    @Autowired
    private PostGISService postGISService;


    //一张图中的项目查询接口
    public List<ProjectResponse> getProjectInfoByFlowType(FlowType flowType) {
        List<ProjectResponse> list = new ArrayList<>();
        //查询报地
        List<ProjectResponse> reportInfoList = reportInfoRepository.findAll().stream().map(reportInfo -> {
            ProjectResponse response = new ProjectResponse();
            response.setCreateTime(reportInfo.getApplyTime());
            response.setId(reportInfo.getId());
            response.setName(reportInfo.getName());
            response.setType(FlowType.REPORT);
            return response;
        }).collect(Collectors.toList());
        //查询批地
        List<ProjectResponse> grantInfoList = grantInfoRepository.findAll().stream().map(grantInfo -> {
            ProjectResponse response = new ProjectResponse();
            response.setCreateTime(grantInfo.getGrantTime());
            response.setId(grantInfo.getId());
            response.setName(grantInfo.getName());
            response.setType(FlowType.GRANT);
            return response;
        }).collect(Collectors.toList());
        List<ProjectResponse> expropriationList = expropriationRepository.findAll().stream().map(expropriation -> {
            ProjectResponse response = new ProjectResponse();
            response.setCreateTime(expropriation.getLevyTime());
            response.setId(expropriation.getId());
            response.setName(expropriation.getName());
            response.setType(FlowType.GRANT);
            return response;
        }).collect(Collectors.toList());
        List<ProjectResponse> supplyInfoList = supplyInfoRepository.findAll().stream().map(supplyInfo -> {
            ProjectResponse response = new ProjectResponse();
            response.setCreateTime(supplyInfo.getSupplyTime());
            response.setId(supplyInfo.getId());
            response.setName(supplyInfo.getName());
            response.setType(FlowType.GRANT);
            return response;
        }).collect(Collectors.toList());
        if (Objects.isNull(flowType)) {
            list.addAll(reportInfoList);
            list.addAll(grantInfoList);
            list.addAll(expropriationList);
            list.addAll(supplyInfoList);
        } else {
            if (flowType.equals(FlowType.REPORT)) {
                list.addAll(reportInfoList);
            } else if (flowType.equals(FlowType.GRANT)) {
                list.addAll(grantInfoList);
            } else if (flowType.equals(FlowType.EXPROPRIA)) {
                list.addAll(expropriationList);
            } else {
                list.addAll(supplyInfoList);
            }
        }
        //按照时间进行降序排序
        Collections.sort(list, new Comparator<ProjectResponse>() {
            @Override
            public int compare(ProjectResponse o1, ProjectResponse o2) {
                if (o1.getCreateTime().getTime() < o2.getCreateTime().getTime()) {
                    return 1;
                } else {
                    return -1;
                }
            }
        });
        return list;
    }

    /**
     * 外业根据类型进行统计
     * @return
     */
    public List<PatrolStatisticalResponse> getStatisticalPatrolByType(StatisticalRequest request){
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
        Integer year = Integer.valueOf(request.getYear());
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        builder.and(qPatrolInfo.status.eq(PatrolStatus.COMPLETE_PATROL));
        if(request.getType() == 1){ //按年份查询
            builder.and(qPatrolInfo.createTime.year().eq(year));
        }else{ //按季度查询
            Integer quarter = Integer.valueOf(request.getQuarterly());
            LocalDate start = DateUtil.quarterStart(request.getYear(),quarter);
            LocalDate end = start.plusMonths(3);
            builder.and(qPatrolInfo.createTime.between(start.toDate(),end.toDate()));
        }
        Long count = patrolInfoRepository.count(builder);
        List<PatrolStatisticalResponse> list = new ArrayList<>();
        Object[] object = null;
        if(request.getType() == 1){
            object = patrolInfoRepository.getStatisticalType(request.getYear());
        }else{
            Integer quarter = Integer.valueOf(request.getQuarterly());
            LocalDate start = DateUtil.quarterStart(request.getYear(),quarter);
            LocalDate end = start.plusMonths(3);
            object = patrolInfoRepository.getStatisticalType(df.format(start.toDate()),df.format(end.toDate()));
        }
        Map<String,PatrolStatisticalResponse> map = new HashMap<>();
        if(object != null){
            for(Object obj : object){
                PatrolStatisticalResponse response = new PatrolStatisticalResponse();
                Object[] objects = ( Object[])obj;
                if(PatrolType.FIELDPATROL.toString().equals(objects[0].toString())){
                    response.setType(PatrolType.FIELDPATROL);
                }else if(PatrolType.LANDDISASTER.toString().equals(objects[0].toString())){
                    response.setType(PatrolType.LANDDISASTER);
                }else{
                    response.setType(PatrolType.OTHERPATROL);
                }
                Integer numer = Integer.valueOf(objects[1].toString());
                response.setNumber(numer);
                BigDecimal ratio = new BigDecimal(Double.valueOf(numer) / count);
                response.setRatio(ratio);
                map.put(response.getType().toString(),response);
            }
        }
        getResultList(map,list);
        return list;
    }

    /**
     * 返回固定类型（三种）
     * @param map
     * @param list
     */
    public void getResultList(Map<String,PatrolStatisticalResponse> map,List<PatrolStatisticalResponse> list){
        if(map.containsKey("LANDDISASTER")){  //地灾巡查
            list.add(map.get("LANDDISASTER"));
        }else{
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setType(PatrolType.LANDDISASTER);
            response.setNumber(0);
            response.setRatio(new BigDecimal(0));
            list.add(response);
        }

        if(map.containsKey("FIELDPATROL")){  //违法用地巡查
            list.add(map.get("FIELDPATROL"));
        }else{
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setType(PatrolType.FIELDPATROL);
            response.setNumber(0);
            response.setRatio(new BigDecimal(0));
            list.add(response);
        }

        if(map.containsKey("OTHERPATROL")){ //其他巡查
            list.add(map.get("OTHERPATROL"));
        }else{
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setType(PatrolType.OTHERPATROL);
            response.setNumber(0);
            response.setRatio(new BigDecimal(0));
            list.add(response);
        }
    }

    /**
     * 外业根据人进行统计
     * @return
     */
    public List<PatrolStatisticalResponse> getStatisticalPatrolByUser(StatisticalRequest request){
        BooleanBuilder builder = new BooleanBuilder();
        QPatrolInfo qPatrolInfo = QPatrolInfo.patrolInfo;
        Integer year = Integer.valueOf(request.getYear());
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd");
        builder.and(qPatrolInfo.status.eq(PatrolStatus.COMPLETE_PATROL));
        if(request.getType() == 1){ //按年份查询
            builder.and(qPatrolInfo.createTime.year().eq(year));
        }else{ //按季度查询
            Integer quarter = Integer.valueOf(request.getQuarterly());
            LocalDate start = DateUtil.quarterStart(request.getYear(),quarter);
            LocalDate end = start.plusMonths(3);
            builder.and(qPatrolInfo.createTime.between(start.toDate(),end.toDate()));
        }
        Long count = patrolInfoRepository.count(builder);
        List<PatrolStatisticalResponse> list = new ArrayList<>();
        Object[] object = null;
        if(request.getType() == 1){
            object = patrolInfoRepository.getStatisticalUser(request.getYear());
        }else{
            Integer quarter = Integer.valueOf(request.getQuarterly());
            LocalDate start = DateUtil.quarterStart(request.getYear(),quarter);
            LocalDate end = start.plusMonths(3);
            object = patrolInfoRepository.getStatisticalUser(df.format(start.toDate()),df.format(end.toDate()));
        }
        if(object != null){
            for(Object obj : object){
                PatrolStatisticalResponse response = new PatrolStatisticalResponse();
                Object[] objects = ( Object[])obj;
                response.setUserName(objects[0].toString());
                Integer numer = Integer.valueOf(objects[1].toString());
                response.setNumber(numer);
                BigDecimal ratio = new BigDecimal(Double.valueOf(numer) / count);
                response.setRatio(ratio);
                list.add(response);
            }
        }
        return list;
    }

    /**
     * 隐患点根据名称统计
     * @return
     */
    public List<PatrolStatisticalResponse> getStatisticalDisasterByName() throws Exception {
        List<PatrolStatisticalResponse> list = new ArrayList<>();
        Map<String, Integer> dataMap = getLayerCodeInfoByName();

        Long count = landDisasterRepository.count();//总数
        Object[] object = landDisasterRepository.getStatisticalName();
        Map<String, Integer> map = new HashMap<>();
        if(object != null){
            for(Object obj : object){
                Object[] objects = ( Object[])obj;
                Integer numer = Integer.valueOf(objects[1].toString());
                map.put(objects[0].toString(), numer);
            }
        }
        count = mergeMap(count, dataMap, map);

        for (Map.Entry<String, Integer> entry : map.entrySet()) {
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setPrefecture(entry.getKey());
            response.setNumber(entry.getValue());
            BigDecimal ratio = new BigDecimal(Double.valueOf(entry.getValue()) / count);
            response.setRatio(ratio);
            list.add(response);
        }
        return list;
    }

    public Map<String, Integer> getLayerCodeInfoByName() throws Exception {
        Map<String, Integer> map = new HashMap<>();
        String layerCode = getLayerCode();
        if (StringUtils.isNotEmpty(layerCode)) {
            List<MapSpotData> list = postGISService.queryMapSpot(null, layerCode);
            for (MapSpotData data : list) {
                Map<String, Object> attr = data.getAttr();
                String value = (String) attr.get("QSDWMC");
                if (map.containsKey(value.trim())) {
                    Integer count = map.get(value.trim()) + 1;
                    map.put(value.trim(), count);
                } else {
                    map.put(value.trim(), 1);
                }
            }
        }
        return map;
    }

    /**
     * 隐患点根据级别统计
     *
     * @return
     */
    public List<PatrolStatisticalResponse> getStatisticalDisasterByGrade(String prefecture) throws Exception {
        List<PatrolStatisticalResponse> list = new ArrayList<>();
        Long count = landDisasterRepository.count(QLandDisaster.landDisaster.districtInfo.districtName.eq(prefecture));//总数
        Object[] object = landDisasterRepository.getStatisticalByGrade(prefecture);
        Map<String, Integer> dataMap = getNameByGrand(prefecture);//图层中的数据源
        Map<String, Integer> tableMap = new HashMap<>();//隐患点表信息的数据源

        Map<String,PatrolStatisticalResponse> map = new HashMap<>();
        if (object != null) {
            for (Object obj : object) {
                Object[] objects = (Object[]) obj;
                Integer numer = Integer.valueOf(objects[1].toString());
                if (objects[0].toString().toLowerCase().equals("BIG")) {
                    tableMap.put("危险性大", numer);
                } else if (objects[0].toString().toLowerCase().equals("MEDIUM")) {
                    tableMap.put("危险性中等", numer);
                } else {  //five
                    tableMap.put("危险性小", numer);
                }
            }
        }
        count = mergeMap(count, dataMap, tableMap);
        for (Map.Entry<String, Integer> entry : tableMap.entrySet()) {
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            if (entry.getKey().equals("危险性大")) {
                response.setGrade(RiskGrand.BIG);
            } else if (entry.getKey().equals("危险性中等")) {
                response.setGrade(RiskGrand.MEDIUM);
            } else {
                response.setGrade(RiskGrand.SMALL);
            }
            response.setNumber(entry.getValue());
            BigDecimal ratio = new BigDecimal(Double.valueOf(entry.getValue()) / count);
            response.setRatio(ratio);
            map.put(response.getGrade().toString(), response);
        }
        setResultMap(map,list);
        return list;
    }

    private Long mergeMap(Long count, Map<String, Integer> dataMap, Map<String, Integer> tableMap) {
        for (Map.Entry<String, Integer> entry : dataMap.entrySet()) {
            count = count + entry.getValue();
            if (tableMap.containsKey(entry.getKey())) {
                Integer sum = tableMap.get(entry.getKey()) + entry.getValue();
                tableMap.put(entry.getKey(), sum);
            } else {
                tableMap.put(entry.getKey(), entry.getValue());
            }
        }
        return count;
    }


    public Map<String, Integer> getNameByGrand(String prefecture) throws Exception {
        Map<String, Integer> map = new HashMap<>();
        String layerCode = getLayerCode();
        if (StringUtils.isNotEmpty(layerCode)) {
            List<MapSpotData> list = postGISService.queryMapSpot(null, layerCode);
            for (MapSpotData data : list) {
                Map<String, Object> attr = data.getAttr();
                String prefectureName = (String) attr.get("QSDWMC");//行政区名称
                String key = (String) attr.get("WXXDJ");//危险级别
                if (prefectureName.trim().equals(prefecture)) {
                    if (map.containsKey(key.trim())) {
                        Integer count = map.get(key.trim()) + 1;
                        map.put(key.trim(), count);
                    } else {
                        map.put(key.trim(), 1);
                    }
                }

            }
        }
        return map;
    }

    /**
     * 返回固定级别
     * @param map
     * @param list
     */
    public void setResultMap(Map<String,PatrolStatisticalResponse> map,List<PatrolStatisticalResponse> list){
        if (map.containsKey("BIG")) {
            list.add(map.get("BIG"));
        }else{
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setRatio(new BigDecimal(0));
            response.setGrade(RiskGrand.BIG);
            response.setNumber(0);
            list.add(response);
        }

        if (map.containsKey("MEDIUM")) {
            list.add(map.get("MEDIUM"));
        }else{
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setRatio(new BigDecimal(0));
            response.setGrade(RiskGrand.MEDIUM);
            response.setNumber(0);
            list.add(response);
        }

        if (map.containsKey("SMALL")) {
            list.add(map.get("SMALL"));
        }else{
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setRatio(new BigDecimal(0));
            response.setGrade(RiskGrand.SMALL);
            response.setNumber(0);
            list.add(response);
        }

    }
    /**
     *
     * @param statisticsModels
     * @param areaTotal
     * @return
     */
    public List<LandStatisticalResponse> getLandStatisticalResponse(List<StatisticsModel> statisticsModels,
                                                                    BigDecimal areaTotal){
        List<LandStatisticalResponse> list = new ArrayList<>();
        Map<String,List<StatisticsModel>> map = new HashMap<>();
        for(StatisticsModel statisticsModel : statisticsModels){
            if(map.containsKey(statisticsModel.getYear())){
                List<StatisticsModel> models = map.get(statisticsModel.getYear());
                models.add(statisticsModel);
                map.put(statisticsModel.getYear(),models);
            }else {
                List<StatisticsModel> models = new ArrayList<>();
                models.add(statisticsModel);
                map.put(statisticsModel.getYear(),models);
            }
        }
        for(Map.Entry<String, List<StatisticsModel>> entry : map.entrySet()){
            LandStatisticalResponse response = new LandStatisticalResponse();
            response.setYear(entry.getKey());
            response.setUnit(AreaUnit.SQUARE_METRE);
            BigDecimal total = new BigDecimal(0);
            List<StatisticsModel> models = entry.getValue();
            for(StatisticsModel model : models){
                total = total.add(model.getAcreage());
            }
            response.setArea(total);
            if (areaTotal.compareTo(BigDecimal.ZERO) == 0) {
                response.setRatio(new BigDecimal(0));
            } else {
                BigDecimal ratio = total.divide(areaTotal, 4, BigDecimal.ROUND_HALF_UP);
                response.setRatio(ratio);
            }
            list.add(response);
        }

        return list;
    }

    /**
     * 单位转换
     * @return
     */
    public void conversion(StatisticsModel statisticsModel){
        switch (statisticsModel.getUnit()){
            case "MU":
                statisticsModel.setAcreage(statisticsModel.getAcreage().multiply(new BigDecimal(666.6666667)));
                break;
            case "HECTARE":
                statisticsModel.setAcreage(statisticsModel.getAcreage().multiply(new BigDecimal(10000)));
                break;
            default:
                break;
        }
        statisticsModel.setUnit("SQUARE_METRE");
    }

    public void setStatisticsModel(List<LandStatisticalResponse> list,Object[] object){
        if (object != null) {
            BigDecimal areaTotal = new BigDecimal(0);
            List<StatisticsModel> statisticsModels = new ArrayList<>();
            for (Object obj : object) {
                Object[] objects = (Object[]) obj;
                StatisticsModel statisticsModel = new StatisticsModel();
                statisticsModel.setAcreage(new BigDecimal(objects[0].toString()));
                statisticsModel.setYear(objects[1].toString());
                statisticsModel.setUnit(objects[2].toString());
                conversion(statisticsModel);
                areaTotal = areaTotal.add(statisticsModel.getAcreage());
                statisticsModels.add(statisticsModel);
            }
            list.addAll(getLandStatisticalResponse(statisticsModels,areaTotal));
        }
    }

    /**
     * 报地数据统计
     *
     * @param request
     * @return
     */
    public List<LandStatisticalResponse> getLandStatisticalReport(StatisticalRequest request) {
        List<LandStatisticalResponse> list = new ArrayList<>();
        List<String> ids = getFlowInfoList(FlowType.REPORT);
        if (request.getType() == 1) { //按年份统计
            if (ids != null && ids.size() > 0) {
                Object[] object = reportInfoRepository.getStaticalReportByYear(ids);
                setStatisticsModel(list,object);
                sortList(list);
            }
        } else { //按照季度统计
            BigDecimal areaTotal = new BigDecimal(0);
            for (int i = 1; i < 5; i++) {
                LandStatisticalResponse response = new LandStatisticalResponse();
                response.setQuarterly(i);
                LocalDate start = DateUtil.quarterStart(request.getYear(), i);
                LocalDate end = start.plusMonths(3);
                BooleanBuilder builder = new BooleanBuilder();
                QReportInfo qReportInfo = QReportInfo.reportInfo;
                builder.and(qReportInfo.id.in(ids));
                builder.and(qReportInfo.applyTime.between(start.toDate(), end.toDate()));
                Iterator<ReportInfo> infoIterator = reportInfoRepository.findAll(builder).iterator();
                BigDecimal area = new BigDecimal(0);
                while (infoIterator.hasNext()) {
                    ReportInfo reportInfo = infoIterator.next();
                    StatisticsModel statisticsModel = new StatisticsModel();
                    statisticsModel.setUnit(reportInfo.getUnit().toString());
                    statisticsModel.setAcreage(reportInfo.getAcreage());
                    conversion(statisticsModel);
                    area = area.add(statisticsModel.getAcreage());
                    areaTotal = areaTotal.add(statisticsModel.getAcreage());
                }
                response.setArea(area);
                response.setUnit(AreaUnit.SQUARE_METRE);
                list.add(response);
            }
            for (LandStatisticalResponse land : list) {
                if (areaTotal.compareTo(BigDecimal.ZERO) == 0) {
                    land.setRatio(new BigDecimal(0));
                } else {
                    BigDecimal ratio = land.getArea().divide(areaTotal, 4, BigDecimal.ROUND_HALF_UP);
                    land.setRatio(ratio);
                }
            }
        }
        return list;
    }


    /**
     * 获取结束流程并且全部是同意的业务id
     *
     * @param type
     * @return
     */
    public List<String> getFlowInfoList(FlowType type) {
        List<FlowInfo> list = new ArrayList<>();
        BooleanBuilder builder = new BooleanBuilder();
        QFlowInfo qFlowInfo = QFlowInfo.flowInfo;
        builder.and(qFlowInfo.type.eq(type));
        builder.and(qFlowInfo.flowStatus.eq(FlowStatus.FINSH));

        Iterator<FlowInfo> infoIterator = flowInfoRepository.findAll(builder).iterator();
        while (infoIterator.hasNext()) {
            FlowInfo flowInfo = infoIterator.next();
            if (exitResult(flowInfo.getId())) {
                list.add(flowInfo);
            }
        }
        List<String> ids = list.stream().map(flowInfo -> flowInfo.getApplyId()).collect(Collectors.toList());
        return ids;
    }

    public boolean exitResult(String flowId) {
        Iterator<FlowHistory> flowHistoryIterator = flowHistoryRepository.findAll(QFlowHistory
                .flowHistory.flowId.eq(flowId)).iterator();
        while (flowHistoryIterator.hasNext()) {
            FlowHistory flowHistory = flowHistoryIterator.next();
            if (flowHistory.getStatus().equals(FlowResultStatus.REFUSE)) {
                return false;
            }
        }
        return true;
    }

    public void sortList(List<LandStatisticalResponse> list) {
        if (list != null && !list.isEmpty()) {
            Collections.sort(list, new Comparator<LandStatisticalResponse>() {
                @Override
                public int compare(LandStatisticalResponse o1, LandStatisticalResponse o2) {
                    int i = Integer.valueOf(o1.getYear()) - Integer.valueOf(o2.getYear());
                    return i;
                }
            });
        }
    }
    /**
     * 批地信息统计
     *
     * @param request
     * @return
     */
    public List<LandStatisticalResponse> getLandStatisticalGrant(StatisticalRequest request) {
        List<LandStatisticalResponse> list = new ArrayList<>();
        List<String> ids = getFlowInfoList(FlowType.GRANT);
        if (request.getType() == 1) { //按年份统计
            if (ids != null && ids.size() > 0) {
                Object[] object = grantInfoRepository.getStaticalGrantInfoByYear(ids);
                setStatisticsModel(list,object);
                sortList(list);
            }
        } else { //按照季度统计
            BigDecimal areaTotal = new BigDecimal(0);
            for (int i = 1; i < 5; i++) {
                LandStatisticalResponse response = new LandStatisticalResponse();
                response.setQuarterly(i);
                LocalDate start = DateUtil.quarterStart(request.getYear(), i);
                LocalDate end = start.plusMonths(3);
                BooleanBuilder builder = new BooleanBuilder();
                QGrantInfo qGrantInfo = QGrantInfo.grantInfo;
                builder.and(qGrantInfo.id.in(ids));
                builder.and(qGrantInfo.grantTime.between(start.toDate(), end.toDate()));
                Iterator<GrantInfo> infoIterator = grantInfoRepository.findAll(builder).iterator();
                BigDecimal area = new BigDecimal(0);
                while (infoIterator.hasNext()) {
                    GrantInfo grantInfo = infoIterator.next();
                    StatisticsModel statisticsModel = new StatisticsModel();
                    statisticsModel.setUnit(grantInfo.getUnit().toString());
                    statisticsModel.setAcreage(grantInfo.getAcreage());
                    conversion(statisticsModel);
                    area = area.add(statisticsModel.getAcreage());
                    areaTotal = areaTotal.add(statisticsModel.getAcreage());
                }
                response.setArea(area);
                response.setUnit(AreaUnit.SQUARE_METRE);
                list.add(response);
            }
            for (LandStatisticalResponse land : list) {
                if (areaTotal.compareTo(BigDecimal.ZERO) == 0) {
                    land.setRatio(new BigDecimal(0));
                } else {
                    BigDecimal ratio = land.getArea().divide(areaTotal,4, RoundingMode.HALF_UP);
                    land.setRatio(ratio);
                }
            }
        }
        return list;
    }

    /**
     * 征地统计
     *
     * @param request
     * @return
     */
    public List<LandStatisticalResponse> getLandStatisticalExpropriation(StatisticalRequest request) {
        List<LandStatisticalResponse> list = new ArrayList<>();
        List<String> ids = getFlowInfoList(FlowType.EXPROPRIA);
        if (request.getType() == 1) { //按年份统计
            if (ids != null && ids.size() > 0) {
                Object[] object = expropriationRepository.getStaticalExpropriatByYear(ids);
                setStatisticsModel(list,object);
                sortList(list);
            }
        } else { //按照季度统计
            BigDecimal areaTotal = new BigDecimal(0);
            for (int i = 1; i < 5; i++) {
                LandStatisticalResponse response = new LandStatisticalResponse();
                response.setQuarterly(i);
                LocalDate start = DateUtil.quarterStart(request.getYear(), i);
                LocalDate end = start.plusMonths(3);
                BooleanBuilder builder = new BooleanBuilder();
                QExpropriation qExpropriation = QExpropriation.expropriation;
                builder.and(qExpropriation.id.in(ids));
                builder.and(qExpropriation.levyTime.between(start.toDate(), end.toDate()));
                Iterator<Expropriation> infoIterator = expropriationRepository.findAll(builder).iterator();
                BigDecimal area = new BigDecimal(0);
                while (infoIterator.hasNext()) {
                    Expropriation expropriation = infoIterator.next();
                    StatisticsModel statisticsModel = new StatisticsModel();
                    statisticsModel.setUnit(expropriation.getUnit().toString());
                    statisticsModel.setAcreage(expropriation.getAcreage());
                    conversion(statisticsModel);
                    area = area.add(statisticsModel.getAcreage());
                    areaTotal = areaTotal.add(statisticsModel.getAcreage());
                }
                response.setArea(area);
                response.setUnit(AreaUnit.SQUARE_METRE);
                list.add(response);
            }
            for (LandStatisticalResponse land : list) {
                if (areaTotal.compareTo(BigDecimal.ZERO) == 0) {
                    land.setRatio(new BigDecimal(0));
                } else {
                    BigDecimal ratio = land.getArea().divide(areaTotal, 4, RoundingMode.HALF_UP);
                    land.setRatio(ratio);
                }
            }
        }
        return list;
    }

    /**
     * 供地统计
     *
     * @param request
     * @return
     */
    public List<LandStatisticalResponse> getLandStatisticalSupply(StatisticalRequest request) {
        List<LandStatisticalResponse> list = new ArrayList<>();
        SimpleDateFormat df = new SimpleDateFormat("yyyy");
        Map<String, BigDecimal> map = new HashMap<>();
        List<String> ids = getFlowInfoList(FlowType.SUPPLY);
        if (request.getType() == 1) { //按年份统计
            if (ids != null && ids.size() > 0) {
                Object[] object = supplyInfoRepository.getStaticalSupplyByYear(ids);
                setStatisticsModel(list,object);
                sortList(list);
            }
        } else { //按照季度统计
            BigDecimal areaTotal = new BigDecimal(0);
            for (int i = 1; i < 5; i++) {
                LandStatisticalResponse response = new LandStatisticalResponse();
                response.setQuarterly(i);
                LocalDate start = DateUtil.quarterStart(request.getYear(), i);
                LocalDate end = start.plusMonths(3);
                BooleanBuilder builder = new BooleanBuilder();
                QSupplyInfo qSupplyInfo = QSupplyInfo.supplyInfo;
                builder.and(qSupplyInfo.id.in(ids));
                builder.and(qSupplyInfo.supplyTime.between(start.toDate(), end.toDate()));
                Iterator<SupplyInfo> infoIterator = supplyInfoRepository.findAll(builder).iterator();
                BigDecimal area = new BigDecimal(0);
                while (infoIterator.hasNext()) {
                    SupplyInfo supplyInfo = infoIterator.next();
                    StatisticsModel statisticsModel = new StatisticsModel();
                    statisticsModel.setUnit(supplyInfo.getUnit().toString());
                    statisticsModel.setAcreage(supplyInfo.getAcreage());
                    conversion(statisticsModel);
                    area = area.add(statisticsModel.getAcreage());
                    areaTotal = areaTotal.add(statisticsModel.getAcreage());
                }
                response.setArea(area);
                response.setUnit(AreaUnit.SQUARE_METRE);
                list.add(response);
            }
            for (LandStatisticalResponse land : list) {
                if (areaTotal.compareTo(BigDecimal.ZERO) == 0) {
                    land.setRatio(new BigDecimal(0));
                } else {
                    BigDecimal ratio = land.getArea().divide(areaTotal, 4, RoundingMode.HALF_UP);
                    land.setRatio(ratio);
                }
            }
        }
        return list;
    }


    public List<LandStatisticalResponse> getLandStatisticalRests(StatisticalRequest request) {
        List<LandStatisticalResponse> list = new ArrayList<>();
        SimpleDateFormat df = new SimpleDateFormat("yyyy");
        Map<String, BigDecimal> map = new HashMap<>();
        List<String> ids = getFlowInfoList(FlowType.RESTS);
        if (request.getType() == 1) { //按年份统计
            if (ids != null && ids.size() > 0) {
                Object[] object = restsInfoRepository.getStaticalRestsByYear(ids);
                setStatisticsModel(list, object);
                sortList(list);
            }
        } else { //按照季度统计
            BigDecimal areaTotal = new BigDecimal(0);
            for (int i = 1; i < 5; i++) {
                LandStatisticalResponse response = new LandStatisticalResponse();
                response.setQuarterly(i);
                LocalDate start = DateUtil.quarterStart(request.getYear(), i);
                LocalDate end = start.plusMonths(3);
                BooleanBuilder builder = new BooleanBuilder();
                QRestsInfo qRestsInfo = QRestsInfo.restsInfo;
                builder.and(qRestsInfo.id.in(ids));
                builder.and(qRestsInfo.createTime.between(start.toDate(), end.toDate()));
                Iterator<RestsInfo> infoIterator = restsInfoRepository.findAll(builder).iterator();
                BigDecimal area = new BigDecimal(0);
                while (infoIterator.hasNext()) {
                    RestsInfo restsInfo = infoIterator.next();
                    StatisticsModel statisticsModel = new StatisticsModel();
                    statisticsModel.setUnit(restsInfo.getUnit().toString());
                    statisticsModel.setAcreage(restsInfo.getAcreage());
                    conversion(statisticsModel);
                    area = area.add(statisticsModel.getAcreage());
                    areaTotal = areaTotal.add(statisticsModel.getAcreage());
                }
                response.setArea(area);
                response.setUnit(AreaUnit.SQUARE_METRE);
                list.add(response);
            }
            for (LandStatisticalResponse land : list) {
                if (areaTotal.compareTo(BigDecimal.ZERO) == 0) {
                    land.setRatio(new BigDecimal(0));
                } else {
                    BigDecimal ratio = land.getArea().divide(areaTotal, 4, RoundingMode.HALF_UP);
                    land.setRatio(ratio);
                }
            }
        }
        return list;
    }


    /**
     * 获取对应的图层中高中低和不易发区统计
     *
     * @return
     * @throws Exception
     */
    public Map<String, Integer> getLayerCodeInfo() throws Exception {
        Map<String, Integer> map = new HashMap<>();
        String layerCode = getLayerCode();
        if (StringUtils.isNotEmpty(layerCode)) {
            List<MapSpotData> list = postGISService.queryMapSpot(null, layerCode);
            for (MapSpotData data : list) {
                Map<String, Object> attr = data.getAttr();
                String value = (String) attr.get("DZYFQ");
                if (map.containsKey(value.trim())) {
                    Integer count = map.get(value.trim()) + 1;
                    map.put(value.trim(), count);
                } else {
                    map.put(value.trim(), 1);
                }
            }
        }
        return map;
    }

    /**
     * 按照易发区级别进行统计
     *
     * @return
     * @throws Exception
     */
    public List<PatrolStatisticalResponse> statSusceptible() throws Exception {
        List<PatrolStatisticalResponse> list = new ArrayList<>();
        Object[] object = landDisasterRepository.getSusceptible();
        Map<String, Integer> dataMap = new HashMap<>();
        if (object != null) {
            for (Object obj : object) {
                Object[] objects = (Object[]) obj;
                String key = objects[0].toString();
                if (dataMap.containsKey(key)) {
                    Integer num = dataMap.get(key) + 1;
                    dataMap.put(key, num);
                } else {
                    dataMap.put(key, 1);
                }
            }
        }
        Integer count = 0;
        Map<String, Integer> map = getLayerCodeInfo();
//        for(Map.Entry<String,Integer> entry : map.entrySet()){
//            count += entry.getValue();
//        }
        if (map.containsKey("高易发区")) {
            if (dataMap.containsKey("HIGH")) {
                Integer sum = dataMap.get("HIGH") + map.get("高易发区");
                dataMap.put("HIGH", sum);
            } else {
                dataMap.put("HIGH", map.get("高易发区"));
            }
            count = count + map.get("高易发区");
        } else {
            dataMap.put("HIGH", 0);
        }

        if (map.containsKey("中易发区")) {
            if (dataMap.containsKey("MEDIUM")) {
                Integer sum = dataMap.get("MEDIUM") + map.get("中易发区");
                dataMap.put("MEDIUM", sum);
            } else {
                dataMap.put("MEDIUM", map.get("中易发区"));
            }
            count = count + map.get("中易发区");
        } else {
            dataMap.put("MEDIUM", 0);
        }

        if (map.containsKey("低易发区")) {
            if (dataMap.containsKey("LOW")) {
                Integer sum = dataMap.get("LOW") + map.get("低易发区");
                dataMap.put("LOW", sum);
            } else {
                dataMap.put("LOW", map.get("低易发区"));
            }
            count = count + map.get("低易发区");
        } else {
            dataMap.put("LOW", 0);
        }

        if (map.containsKey("不易发区")) {
            if (dataMap.containsKey("NONE")) {
                Integer sum = dataMap.get("NONE") + map.get("不易发区");
                dataMap.put("NONE", sum);
            } else {
                dataMap.put("NONE", map.get("不易发区"));
            }
            count = count + map.get("不易发区");
        } else {
            dataMap.put("NONE", 0);
        }

        for (Map.Entry<String, Integer> entry : dataMap.entrySet()) {
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            switch (entry.getKey().trim()) {
                case "HIGH":
                    response.setSusceptible(SusceptibleGrand.HIGH);
                    break;
                case "MEDIUM":
                    response.setSusceptible(SusceptibleGrand.MEDIUM);
                    break;
                case "LOW":
                    response.setSusceptible(SusceptibleGrand.LOW);
                    break;
                case "NONE":
                    response.setSusceptible(SusceptibleGrand.NONE);
                    break;
                default:
                    break;
            }
            Integer numer = Integer.valueOf(entry.getValue());
            response.setNumber(numer);
            BigDecimal ratio = new BigDecimal(Double.valueOf(numer) / count);
            response.setRatio(ratio);
            list.add(response);
        }
        return list;
    }


    public List<PatrolStatisticalResponse> statSusceptibleAndGrad(SusceptibleGrand susceptible) throws Exception {
        String param = getGrandMark(susceptible);
        Map<String, Integer> layerMap = getLayerCodeInfoByGrand(param);

        List<PatrolStatisticalResponse> list = new ArrayList<>();
        Long count = landDisasterRepository.count(QLandDisaster.landDisaster.districtInfo.susceptible.eq(susceptible));//总数
        Object[] object = landDisasterRepository.getSusceptibleByGrade(susceptible.toString());
        Map<String, PatrolStatisticalResponse> map = new HashMap<>();
        Map<String, Integer> tableMap = new HashMap<>();
        if (object != null) {
            for (Object obj : object) {
                Object[] objects = (Object[]) obj;
                Integer numer = Integer.valueOf(objects[1].toString());
                String key = objects[0].toString();
                if (key.equals("BIG")) {
                    tableMap.put("危险性大", numer);
                } else if (key.equals("MEDIUM")) {
                    tableMap.put("危险性中等", numer);
                } else {
                    tableMap.put("危险性小", numer);
                }
            }
        }
        count = mergeMap(count, layerMap, tableMap);

        for (Map.Entry<String, Integer> entry : tableMap.entrySet()) {
            PatrolStatisticalResponse response = new PatrolStatisticalResponse();
            response.setGrade(getGrandValue(entry.getKey()));
            response.setNumber(entry.getValue());
            BigDecimal ratio = new BigDecimal(Double.valueOf(entry.getValue()) / count);
            response.setRatio(ratio);
            map.put(response.getGrade().toString(), response);
        }
        setResultMap(map, list);
        return list;
    }

    public RiskGrand getGrandValue(String key) {
        if (key.equals("危险性大")) {
            return RiskGrand.BIG;
        } else if (key.equals("危险性中等")) {
            return RiskGrand.MEDIUM;
        } else {
            return RiskGrand.SMALL;
        }
    }

    public String getGrandMark(SusceptibleGrand susceptible) {
        String mark = new String();
        if (susceptible != null) {
            switch (susceptible) {
                case HIGH:
                    mark = "高易发区";
                    break;
                case MEDIUM:
                    mark = "中易发区";
                    break;
                case LOW:
                    mark = "低易发区";
                    break;
                case NONE:
                    mark = "不易发区";
                    break;
                default:
                    break;
            }
        }
        return mark;
    }


    public Map<String, Integer> getLayerCodeInfoByGrand(String grand) throws Exception {
        Map<String, Integer> map = new HashMap<>();
        String layerCode = getLayerCode();
        if (StringUtils.isNotEmpty(layerCode)) {
            List<MapSpotData> list = postGISService.queryMapSpot(null, layerCode);
            for (MapSpotData data : list) {
                Map<String, Object> attr = data.getAttr();
                String susce = (String) attr.get("DZYFQ");//已发级别
                String key = (String) attr.get("WXXDJ");//危险级别
                if (susce.trim().equals(grand)) {
                    if (map.containsKey(key.trim())) {
                        Integer count = map.get(key.trim()) + 1;
                        map.put(key.trim(), count);
                    } else {
                        map.put(key.trim(), 1);
                    }
                }

            }
        }
        return map;
    }

    private String getLayerCode() {
        BooleanBuilder builder = new BooleanBuilder();
        QLayerRelation qLayerRelation = QLayerRelation.layerRelation;
        builder.and(qLayerRelation.type.eq(LayerRelate.DZDFB));
        LayerRelation relation = layerRelationRepository.findOne(builder).orElse(new LayerRelation());
        if (Objects.nonNull(relation)) {
            return relation.getLayerCode();
        } else {
            return null;
        }
    }
}
